#include <stdlib.h>
#include <string.h>

#include "main.h"
#include "bdos.h"

unsigned int tstates=0;

Z80EX_BYTE memory[MEMORY_SIZE];

void quit()
{
	printf("\n");
	exit(0);
}

Z80EX_BYTE mread_cb(Z80EX_CONTEXT *cpu, Z80EX_WORD addr, int m1_state, void *user_data)
{
/*	if ((addr < 0x100 && addr != 5) || addr > 0xFE00)
		printf("Accessing %04x from %04x\n", addr, z80ex_get_reg(cpu, regPC)); */
	if (addr > 0xFE00)
		printf("Accessing BIOS at %04x from %04x\n", addr, z80ex_get_reg(cpu, regPC));
	if (m1_state == 1) // Hooks for CP/M system calls
	{
		if (addr == 0x05)
		{
			Z80EX_WORD bc = z80ex_get_reg(cpu, regBC);
			Z80EX_WORD de = z80ex_get_reg(cpu, regDE);
			
			bdos_call(cpu, bc & 0xFF, de);
			
			return 0xC9;
		}
		
		if (addr == 0) quit();

		if (addr == 0x38) return 0xED;
		if (addr == 0x39) return 0x4D;
	}
	
	return memory[addr];
}

void mwrite_cb(Z80EX_CONTEXT *cpu, Z80EX_WORD addr, Z80EX_BYTE value, void *user_data)
{
	memory[addr] = value;
}

Z80EX_BYTE pread_cb(Z80EX_CONTEXT *cpu, Z80EX_WORD port, void *user_data)
{
	printf("Read port\n");
	return 0xFF;
}

void pwrite_cb(Z80EX_CONTEXT *cpu, Z80EX_WORD port, Z80EX_BYTE value, void *user_data)
{
	printf("Write port\n");
}

Z80EX_BYTE intread_cb(Z80EX_CONTEXT *cpu, void *user_data)
{
	return 0xFF;
}

int main(int argc, char** argv)
{
	get_directory();
	if (argc == 1)
	{
		printf("Usage: cpmemu <cpmfile.com>\n");
		return 1;
	}

	/*FILE* f = fopen("bios.bin", "r");
	fread(&memory[0xFE00], 1, 480, f);
	fclose(f);*/

	FILE* file = fopen(argv[1], "rb");
	if (fread(&memory[0x100], 1, MEMORY_SIZE, file) == 0)
	{
		printf("File is empty\n");
		return 1;
	}
	fclose(file);
	
	Z80EX_CONTEXT* cpu = z80ex_create(
		mread_cb, NULL, mwrite_cb,
		NULL, pread_cb, NULL, 
		pwrite_cb, NULL,
		intread_cb, NULL);
		
	z80ex_set_reg(cpu, regPC, 0x100);
	
	memory[0x06] = 0x00;
	memory[0x07] = 0xFE;
	
	if (argc < 3)
	{
		memory[0x80] = 0x00;
		memory[0x81] = 0x0D;
	}
	else
	{
		memory[0x80] = strlen(argv[2]) + 1;
		memory[0x81] = ' ';
		strcpy((char*)(&memory[0x82]), (const char*)argv[2]);
	}
	
	while (1)
	{
		tstates += z80ex_step(cpu);
		//printf("%04x\n", z80ex_get_reg(cpu, regPC));
	}
	
	quit();
}
